package com.samphanie.common.execetion;

import cn.hutool.core.util.StrUtil;
import com.samphanie.common.enums.ResultCode;
import com.samphanie.common.utils.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.io.FileNotFoundException;

/**
 * 处理全局异常
 *
 * @author ZSY
 */
@Slf4j
@RestControllerAdvice(basePackages = "com.samphanie")
public class GlobalExceptionHandler {

    @ResponseBody
    @ExceptionHandler(value = ApiException.class)
    public ApiResponse<?> handleApiException(ApiException exception) {
        log.error("程序异常==>errorCode:{}, exception:{}", HttpStatus.NOT_FOUND.value(), exception.getMessage());
        log.error("程序异常：" + exception);
        log.error("错误堆栈信息: {}", exception.getStackTrace()[0]);
        String message = exception.getMessage();
        if (exception.getErrorCode() != null) {
            return ApiResponse.failed(exception.getErrorCode());
        }
        if (StringUtils.contains(message, "Bad credentials")) {
            message = "用户不存在或密码错误";
        }
        if (StringUtils.contains(message, "InternalAuthenticationServiceException")) {
            message = "用户不存在或密码错误";
        }
        if (StringUtils.containsIgnoreCase(message, "Invalid refresh token (expired)")) {
            message = "刷新令牌已过期，请重新登录";
        }
        if (StrUtil.containsIgnoreCase(message, "Invalid refresh token")) {
            message = "refresh token无效";
        }
        if (StrUtil.containsIgnoreCase(message, "Invalid authorization code")) {
            message = "authorization code无效";
        }
        if (StrUtil.containsIgnoreCase(message, "locked")) {
            message = "用户已被锁定，请联系管理员";
        }
        if (StrUtil.containsIgnoreCase(message, "User is disabled")) {
            return ApiResponse.failed(ResultCode.USER_ERROR_A0202);
        }
        if (StrUtil.startWith(message, "Unable to find instance for")) {
            message = "服务器异常";
        }
        return ApiResponse.failed(message);
    }

    /**
     * 统一表单验证
     */
    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ApiResponse<?> handleNotValidException(MethodArgumentNotValidException exception) {
        log.error("程序异常==>errorCode:{}, exception:{}", HttpStatus.NOT_FOUND.value(), exception.getMessage());
        log.error("程序异常：" + exception);
        log.error("错误堆栈信息: {}", exception.getStackTrace()[0]);
        BindingResult bindingResult = exception.getBindingResult();
        FieldError fieldError = bindingResult.getFieldErrors().get(0);
        //        Map<String, String> errorMap = new HashMap<>();
        //        bindingResult.getFieldErrors().forEach(fieldError -> {
        //            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
        //        });
        return ApiResponse.failed(ResultCode.USER_ERROR_A0421.getCode(), fieldError.getDefaultMessage());
    }

    /**
     * FileNotFoundException,NoHandlerFoundException 异常捕获处理
     *
     * @param exception 自定义FileNotFoundException异常类型
     * @return Result
     */
    @ExceptionHandler({FileNotFoundException.class, NoHandlerFoundException.class})
    public ApiResponse<?> noFoundException(Exception exception) {
        log.error("程序异常==>errorCode:{}, exception:{}", HttpStatus.NOT_FOUND.value(), exception.getMessage());
        log.error("程序异常：" + exception);
        log.error("错误堆栈信息: {}", exception.getStackTrace()[0]);
        return ApiResponse.failed(HttpStatus.NOT_FOUND.value(), exception.getMessage());
    }

    /**
     * 通用Exception异常捕获
     *
     * @param ex 自定义Exception异常类型
     * @return Result
     */
    @ExceptionHandler
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiResponse<?> handleException(Exception ex) {
        log.error("程序异常==>errorCode:{}, exception:{}", HttpStatus.NOT_FOUND.value(), ex.getMessage());
        log.error("程序异常：" + ex);
        log.error("错误堆栈信息: {}", ex.getStackTrace()[0]);
        String message = ex.getMessage();
        if (StrUtil.startWith(message, "Unable to find instance for")) {
            message = "服务器异常";
        }
        if (StrUtil.startWith(message, "User is disabled")) {
            return ApiResponse.failed(ResultCode.USER_ERROR_A0202);
        }
        return ApiResponse.failed(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);
    }

}
